package mylib.dir;

import java.util.Random;

/**
 * Created with IntelliJ IDEA.
 * User: 1
 * Date: 20.07.12
 * Time: 17:27
 * To change this template use File | Settings | File Templates.
 */
public class HashInfo {
    public int modulo1, modulo2;
    public int point1, point2;
    public int[] power1, power2;
    public int[] inversePower1, inversePower2;
    //private static Random random = new Random(System.nanoTime());
    private static Random random = new Random(390258932085L);

    public HashInfo(int len) {
        initPoints();
        initModulus();
        initPowers(len);
    }

    public long Merge(long h1, int p1, long h2, int p2) {
        int x1 = (int) (h1 >> 32);
        int y1 = (int) h1;
        int x2 = (int) (h2 >> 32);
        int y2 = (int) (h2);
        x2 = (int) ((long) x2 * power1[p2] % modulo1);
        y2 = (int) ((long) y2 * power2[p2] % modulo2);
        x1 += x2;
        if (x1 >= modulo1) x1 -= modulo1;
        y1 += y2;
        if (y1 >= modulo2) y1 -= modulo2;
        return ((long) x1 << 32) + y1;
    }

    private void initPoints() {
        do {
            do {
                point1 = random.nextInt(100) + 26;
            } while (!MathUtils.fastPrime(point1));
            do {
                point2 = random.nextInt(100) + 26;
            } while (!MathUtils.fastPrime(point2));
        } while (point1 == point2);
    }

    private void initPowers(int len) {
        power1 = new int[len];
        power2 = new int[len];
        inversePower1 = new int[len];
        inversePower2 = new int[len];
        power1[0] = 1;
        power2[0] = 1;

        inversePower1[0] = 1;
        inversePower2[0] = 1;
        int rev1 = MathUtils.inverse(point1, modulo1);
        int rev2 = MathUtils.inverse(point2, modulo2);
        for (int i = 1; i < len; ++i) {
            power1[i] = (int) ((long) power1[i - 1] * point1 % modulo1);
            power2[i] = (int) ((long) power2[i - 1] * point2 % modulo2);
            inversePower1[i] = (int) ((long) inversePower1[i - 1] * rev1 % modulo1);
            inversePower2[i] = (int) ((long) inversePower2[i - 1] * rev2 % modulo2);
        }
    }

    private void initModulus() {
        do {
            do {
                modulo1 = random.nextInt((1 << 29) - 1) + (1 << 29);
            } while (!MathUtils.fastPrime(modulo1));
            do {
                modulo2 = random.nextInt((1 << 29) - 1) + (1 << 29);
            } while (!MathUtils.fastPrime(modulo2));
        } while (modulo1 == modulo2);
    }
}
